package pri.damai.xiaowu.auth.security.authorization;

import pri.damai.xiaowu.auth.security.loginlogic.LoginLogicFactory;
import pri.damai.xiaowu.auth.security.loginlogic.LoginTypeEnums;
import pri.damai.xiaowu.auth.security.loginlogic.base.AbstractLoginLogic;
import pri.damai.xiaowu.auth.security.model.LoginData;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import pri.damai.xiaowu.common.core.util.EnumUtils;

import javax.annotation.Resource;
import java.util.Objects;

/**
 * 认证用户
 * @Desc 这里是 核心验证方法
 * @Author DaMai
 * @Date 2021/10/13 17:47
 * 但行好事，莫问前程。
 */
@Slf4j
@Component
public class RuiRuanAuthenticationTokenProvider implements AuthenticationProvider {

    @Resource
    LoginLogicFactory loginLogicFactory;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {

        // 前置参数验证
        RuiRuanAuthenticationToken ruiRuanAuthenticationToken = (RuiRuanAuthenticationToken) authentication;
        log.debug(ruiRuanAuthenticationToken.toString());
        LoginData loginData = ruiRuanAuthenticationToken.getLoginData();
        if (loginData == null) {
            throw new AuthenticationServiceException("未获取到登陆参数");
        }
        String loginType = loginData.getLoginType();
        if (Objects.isNull(loginType)) {
            throw new AuthenticationServiceException("登陆方式不可为空");
        }

        // 不同验证途径 --> 不同验证逻辑
        AbstractLoginLogic loginLogic = loginLogicFactory.getLoginLogic(EnumUtils.getEnumByValue(LoginTypeEnums.class,loginType));
        UserDetails userDetails = loginLogic.authenticate(loginData);

        RuiRuanAuthenticationToken token = new RuiRuanAuthenticationToken(userDetails, loginData.getPassword(), userDetails.getAuthorities());
        token.setLoginData(loginData);
        token.setDetails(userDetails);
        token.setAuthenticated(Boolean.TRUE);

        return token;
    }

    public void setLoginLogicFactory(LoginLogicFactory loginLogicFactory) {
        this.loginLogicFactory = loginLogicFactory;
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return (RuiRuanAuthenticationToken.class.isAssignableFrom(authentication));
    }

}
